/**
 * 
 */
package javavis.jip2d.functions;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.LinkedList;

import javavis.base.JIPException;
import javavis.base.JIPToolkit;
import javavis.base.parameter.JIPParamDir;
import javavis.base.parameter.JIPParamFile;
import javavis.base.parameter.JIPParamInt;
import javavis.jip2d.base.FunctionGroup;
import javavis.jip2d.base.JIPFunction;
import javavis.jip2d.base.JIPImage;
import javavis.jip2d.base.bitmaps.JIPBmpColor;
import javavis.jip2d.functions.tia2012.AdaBoost;
import javavis.jip2d.functions.tia2012.Feature;
import javavis.jip2d.functions.tia2012.Feature2H;
import javavis.jip2d.functions.tia2012.Feature2V;
import javavis.jip2d.functions.tia2012.Feature3H;
import javavis.jip2d.functions.tia2012.Feature3V;
import javavis.jip2d.functions.tia2012.Feature4X;
import javavis.jip2d.functions.tia2012.StrongLearner;
import javavis.jip2d.functions.tia2012.TrainExample;

/**
 * @author asc
 * 
 */
public class FFaceLearning extends JIPFunction
{

    private ArrayList<Feature>      listaCaracteristicas;
    private ArrayList<TrainExample> listaCaras;
    private ArrayList<TrainExample> listaNoCaras;
    private TrainExample[] listCaras;
    private TrainExample[] listNoCaras;
    private Feature[] listFeature;
    AdaBoost boosting;

    /**
	 * 
	 */
    public FFaceLearning()
    {
        name = "FFaceLearning";
        description = "Realiza el entrenamiento para la deteccion de caras.";
        groupFunc = FunctionGroup.Applic;

        JIPParamDir rutaCaras = new JIPParamDir("Caras", false, true);
        rutaCaras.setDescription("Ruta de la carpeta con los ejemplos de caras");
        addParam(rutaCaras);

        JIPParamDir rutaNoCaras = new JIPParamDir("NoCaras", false, true);
        rutaNoCaras.setDescription("Ruta de la carpeta con los ejemplos de no-caras");
        addParam(rutaNoCaras);

        JIPParamDir rutaAdaBoost = new JIPParamDir("AdaBoost", false, true);
        rutaAdaBoost.setDescription("Ruta de un fichero que contiene un AdaBoost");
        addParam(rutaAdaBoost);

        JIPParamInt iteraciones = new JIPParamInt("Iteraciones", false, true);
        iteraciones.setDescription("Numero de iteraciones a realizar por el algoritmo");
        addParam(iteraciones);

        JIPParamInt threads = new JIPParamInt("Threads", false, true);
        threads.setDescription("Numero de threads a utilizar");
        addParam(threads);

    }

    /*
     * (non-Javadoc)
     * @see
     * javavis.jip2d.base.JIPFunction#processImg(javavis.jip2d.base.JIPImage)
     */
    @SuppressWarnings("unused")
    @Override
    public JIPImage processImg(JIPImage img) throws JIPException
    {
        // TODO Auto-generated method stub
        if(true)
        {
            String lect="-1";
            if(lect!="-1")lectura(lect);
            if(boosting == null)
            {
                listaNoCaras = new ArrayList<TrainExample>();
                listaCaras = new ArrayList<TrainExample>();
                listaCaracteristicas = new ArrayList<Feature>();
                
                leerNoCaras();
                leerCaras();
                generaFeatures();
                
                listCaras = new TrainExample[listaCaras.size()];
                listCaras = listaCaras.toArray(listCaras);
                listaCaras=null;
                listNoCaras = new TrainExample[listaNoCaras.size()];
                listNoCaras = listaNoCaras.toArray(listNoCaras);
                listaNoCaras = null;
                
                listFeature = new Feature[listaCaracteristicas.size()];
                listFeature =  listaCaracteristicas.toArray(listFeature);
                listaCaracteristicas = null;
                
                
                //boosting = new AdaBoost(listaCaracteristicas,listaCaras,listaNoCaras);
                boosting = new AdaBoost(listFeature,listCaras,listNoCaras);
            }
    
            //System.out.print(listaCaracteristicas.size());
            for(int i=Integer.parseInt(lect)+1; i<10; i++)
            {
                boosting.AlgoritmoAdaBoost();
                escritura(String.valueOf(i));
            }
        }
        else
            Test();
        
        return img;
    }

    public void lectura(String ent){


        FileInputStream fis = null;
        ObjectInputStream in = null;
        try
        {
            fis = new FileInputStream(getParamValueString("AdaBoost") + "adaboost."+ent);
            in = new ObjectInputStream(fis);
            boosting = (AdaBoost)in.readObject();
        } catch(IOException ioe)
        {
            System.err.println("Error de entrada/salida");
        }catch (ClassNotFoundException cnfe)
        {
            System.err.println("Error de Clase no encontrada");
        }
        catch (JIPException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void escritura(String salida){

        FileOutputStream fos=null;
        ObjectOutputStream oos=null;
        try {
            fos = new FileOutputStream(getParamValueString("AdaBoost") + "adaboost."+salida);
            oos = new ObjectOutputStream(fos);
            oos.writeObject(boosting);
        }
        catch (Exception e) {
            System.out.println("No se pudo guardar el fichero con el resultado del aprendizaje");
            System.out.println(e);
        }
        finally {
            try {
                if (oos != null && fos != null) {
                    oos.close();
                    fos.close();
                }
            }
            catch (Exception e) {System.out.println(e);}
        }
    }
 
    
    
    /**
     * @throws JIPException
     */
    private void leerNoCaras() throws JIPException
    {
        JIPBmpColor input;
        String pathFile;
        String pathFolder = getParamValueString("NoCaras");
        File folder = new File(pathFolder);
        if (!folder.isDirectory()) throw new JIPException("La ruta especificada no es un directorio");
        File[] fileNames = folder.listFiles();

        for (File file : fileNames)
        {
            pathFile = file.getAbsolutePath();
            if (pathFile.endsWith(".jpg") || pathFile.endsWith(".gif")) 
            try
            {
                input = (JIPBmpColor) JIPToolkit.getColorImage(JIPToolkit.getAWTImage(pathFile));
                listaNoCaras.add(new TrainExample(input, false));
            }
            catch (Exception e)
            {
                System.out.println("Error openning " + pathFile + "\n" + e);
            }
        }

    }

    /**
     * @throws JIPException
     */
    private void leerCaras() throws JIPException
    {
        JIPBmpColor input;
        String pathFile;
        String pathFolder = getParamValueString("Caras");
        File folder = new File(pathFolder);
        if (!folder.isDirectory()) throw new JIPException("La ruta especificada no es un directorio");
        File[] fileNames = folder.listFiles();

        for (File file : fileNames)
        {
            pathFile = file.getAbsolutePath();
            if (pathFile.endsWith(".jpg") || pathFile.endsWith(".gif"))
            try
            {
                input = (JIPBmpColor) JIPToolkit.getColorImage(JIPToolkit.getAWTImage(pathFile));
                listaCaras.add(new TrainExample(input, true));
            }
            catch (Exception e)
            {
                System.out.println("Error openning " + pathFile + "\n" + e);
            }
        }

    }

    /**
	 * 
	 */
    private void generaFeatures()
    {
        for (int i = 0; i < 24; i++)
        { // Recorrido Filas
            for (int j = 0; j < 24; j++)
            { // Recorrido Columnas
                for (int j2 = 0; j2 <= 24; j2++)
                { // Recorrido ancho
                    for (int k = 0; k <= 24; k++)
                    { // Recorrido alto
                        try
                        {
                            listaCaracteristicas.add((Feature)new Feature2H(i, j, j2, k));
                        }
                        catch (Exception e)
                        {
                        }
                        try
                        {
                            listaCaracteristicas.add((Feature)new Feature2V(i, j, j2, k));
                        }
                        catch (Exception e)
                        {
                        }
                        try
                        {
                            listaCaracteristicas.add((Feature)new Feature3H(i, j, j2, k));
                        }
                        catch (Exception e)
                        {
                        }
                        try
                        {

                            listaCaracteristicas.add((Feature)new Feature3V(i, j, j2, k));
                        }
                        catch (Exception e)
                        {
                        }
                        try
                        {
                            listaCaracteristicas.add((Feature)new Feature4X(i, j, j2, k));
                        }
                        catch (Exception e)
                        {
                        }
                    }
                }
            }
        }
    }
    
    void Test()
    {
        listaNoCaras = new ArrayList<TrainExample>();
        listaCaras = new ArrayList<TrainExample>();
        try
        {
            leerNoCaras();
            leerCaras();
        }
        catch (JIPException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("CB:CM:NCB:NCM:T");
        for(int i=0; i<10; i++)
        {
            lectura(String.valueOf(i));
            
            StrongLearner clasificadorFuerte = boosting.clasificadorFuerte;
            
            clasificadorFuerte.setAlto(0);
            clasificadorFuerte.setAncho(0);
            
            int carasBien = 0;
            int carasMal = 0;
            int noCarasBien =0;
            int noCarasMal = 0;
            long tiempoTotal = 0;
            long tiempoMedio = 0;
            long tInicio;
            long tFinal;
            
            for (TrainExample train : listaCaras)
            {
                tInicio = System.currentTimeMillis();
                
                if(clasificadorFuerte.Clasifica(train.getIntegral()))
                {
                    carasBien++;
                }
                else
                {
                    carasMal++;
                }
                
                tFinal = System.currentTimeMillis();
                tiempoTotal += tFinal-tInicio;
            }
            
            for (TrainExample train : listaNoCaras)
            {
                tInicio = System.currentTimeMillis();
                
                if(!clasificadorFuerte.Clasifica(train.getIntegral()))
                {
                    noCarasBien++;
                }
                else
                {
                    noCarasMal++;
                }
                
                tFinal = System.currentTimeMillis();
                tiempoTotal += tFinal-tInicio;
            }
            tiempoMedio = tiempoTotal/(listaCaras.size()+listaNoCaras.size());
            System.out.println(carasBien + ":" + carasMal + ":" + noCarasBien + ":" + noCarasMal + ":" + tiempoTotal);
            clasificadorFuerte=null;
            boosting=null;
        }
    }
    
    
}
